using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Input;
using Core;
using Core.Domain.Entities;
using Core.Domain.Enums;
using Core.Interfaces;
using Core.Settings;
using DataMain;

namespace TallyJ.FrontDesk
{
  ///<summary>Presenter for the FrontDesk</summary>
  public class FrontDeskPresenter
  {
    private readonly ISessionProvider _sessionProvider;
    private List<Voter> _voters;
    private IFrontDeskView _view;

    ///<summary>Default. Creates new window.</summary>
    public FrontDeskPresenter() : this(new FrontDeskWindow(), IoC.Container.Resolve<ISessionProvider>())
    {
    }

    ///<summary>Can inject another view</summary>
    ///<param name="view"></param>
    public FrontDeskPresenter(IFrontDeskView view)
          : this(view, IoC.Container.Resolve<ISessionProvider>())
    {
    }

    ///<summary>Can inject another view</summary>
    ///<param name="view"></param>
    ///<param name="sessionProvider"></param>
    public FrontDeskPresenter(IFrontDeskView view, ISessionProvider sessionProvider)
    {
      FrontDeskDataContext = new FrontDeskDataContext();

      _view = view;
      _sessionProvider = sessionProvider;
      _view.LocalDataContext = FrontDeskDataContext;
      _view.Presenter = this;
      //_view.ViewDispatcherAction(Load);
      Load();

      InputChanged(null, null);
    }

    private FrontDeskDataContext FrontDeskDataContext { get; set; }


    private void Load()
    {
      var settings = IoC.Container.Resolve<IEnvironment>();
   
      _voters = (from voter in settings.Election.Voters
                 where voter.PersonVoting.IsAdultInGoodStanding()
                 orderby voter.PersonVoting.SortableName()
                 select voter).ToList();
    }

    ///<summary>Start this view</summary>
    public void Show()
    {
      _view.Show();
    }

    ///<summary>Start this view as a dialog</summary>
    public void ShowDialog()
    {
      _view.ShowDialog();
    }

    ///<summary></summary>
    ///<param name="sender"></param>
    ///<param name="e"></param>
    public void OnMouseWheel(object sender, MouseWheelEventArgs e)
    {
      var x = (e.Delta < 0
                     ? 1
                     : (e.Delta > 0
                              ? -1
                              : 0));
    }

//    public event EventHandler<XeArg> DoAnimation;

    ///<summary>
    ///</summary>
    ///<param name="sender">Can be null</param>
    ///<param name="e1">can be null</param>
    public void InputChanged(object sender, TextChangedEventArgs e1)
    {
      var text = _view.InputText;
      const int top = 20;

      var matched = (from v in _voters
                     where
                           v.PersonVoting.FirstName.DefaultingTo(string.Empty).StartsWith(text,
                                                                             StringComparison.CurrentCultureIgnoreCase) ||
                           v.PersonVoting.LastName.DefaultingTo(string.Empty).StartsWith(text,
                                                                            StringComparison.CurrentCultureIgnoreCase) ||
                           // for other names, need to search inside...
                           v.PersonVoting.OtherFirstNames.DefaultingTo(string.Empty).StartsWith(text,
                                                                                   StringComparison.
                                                                                         CurrentCultureIgnoreCase) ||
                           v.PersonVoting.OtherLastNames.DefaultingTo(string.Empty).StartsWith(text,
                                                                                  StringComparison.
                                                                                        CurrentCultureIgnoreCase)
                     select new ResultItem(false)
                     {
                       Name = v.PersonVoting.DisplayName(true),
                       Method = v.BallotSubmissionMethod,
                       Voter = v
                     }).Take(top);
//
//      // fill in the Voter info
//      var election = IoC.Container.Resolve<IEnvironment>().Election;
//      var voters = election.Voters;
//
//      var results = from p in matched
//                    join voter in voters on p equals voter.PersonVoting into personVoter
//                    from pv in personVoter.DefaultIfEmpty(new Voter
//                                                            {
//                                                                  PersonVoting = p,
//                                                                  BallotSubmissionMethod =
//                                                                        BallotSubmissionMethod.NotSubmitted
//                                                            })
//                    select new ResultItem(true)
//                             {
//                                   Name = p.DisplayName(true),
//                                   Method = pv.BallotSubmissionMethod,
//                                   Voter = pv
//                             };

      FrontDeskDataContext.Matching = matched;

      /*

      var observableCollection = FrontDeskDataContext.Matching;
      var displayed = new Person[observableCollection.Count];

      observableCollection.CopyTo(displayed, 0);

      // remove unused
      foreach (var displayedPerson in displayed)
      {
        if(!newList.Contains(displayedPerson))
        {
          observableCollection.Remove(displayedPerson);
        }
      }
      // add new
      foreach (var newPerson in newList)
      {
        if(!_view.Matching.Contains(newPerson))
        {
          observableCollection.Add(newPerson);
        }
      }
*/
    }

    ///<summary>Save this vote</summary>
    ///<param name="voter"></param>
    ///<param name="method"></param>
    ///<exception cref="ApplicationException"></exception>
    public void SaveVote(Voter voter, BallotSubmissionMethod method)
    {
      var settings = IoC.Container.Resolve<IEnvironment>();

      voter.AtLocation = settings.Location;
      voter.ReceivedByTeller = settings.Teller;
      voter.WhenSubmitted = DateTime.Now;
      voter.Election = settings.Election;
      voter.BallotSubmissionMethod = method;

      if (voter.IsValid)
      {
        // TODO: glittle 2009-04-20 - Add to business action log in DB

        var session = 0.GetSession();
        using (var trans = session.BeginTransaction())
        {
          session.SaveOrUpdate(voter);
          trans.Commit();
        }
      }
      else
      {
        throw new ApplicationException("Tried to save invalid voter info.");
      }
    }
  }
}